# coding=utf-8
# author='kungege21'
# date=2023/8/7 14:25
from typing import Optional, Union

from fastapi import APIRouter, Form, File, UploadFile, HTTPException
from pydantic import BaseModel, EmailStr
from starlette import status

app04 = APIRouter()


"""Response Model 响应模型"""


class UserIn(BaseModel):
    username: str
    password: str
    email: EmailStr
    mobile: str = '10086'
    address: str = None
    full_name: Optional[str] = None


class UserOut(BaseModel):
    username: str
    email: EmailStr
    mobile: str = '10086'
    address: str = None
    full_name: Optional[str] = None


users = {
    'user01': {'username': 'user01', 'password': '123', 'email': 'user01@example.com'},
    'user02': {'username': 'user02', 'password': '456', 'email': 'user02@example.com', 'mobile': '12315', 'full_name': 'zkl'}
}


@app04.post('/response_model', response_model=UserOut, response_model_exclude_unset=True,)
def response_model(user: UserIn):
    print(user.password)
    return users['user02']


@app04.post('/response_model/attributes', response_model=Union[UserIn, UserOut])
def response_model_attributes(user: UserIn):
    # response_model=Union[UserIn, UserOut]
    # response_model=List[UserIn, UserOut]
    # response_model_include=['username']
    # del user.password
    return user


"""Response Status Code 响应状态码"""


@app04.post('/status_code', status_code=200)
async def status_code():
    return {'status_code': 200}


@app04.post('/status_attributes', status_code=status.HTTP_301_MOVED_PERMANENTLY)
async def status_attributes():
    return {'status_code': status.HTTP_301_MOVED_PERMANENTLY}


"""Form Data 表单数据处理"""


@app04.post('login')
def login(username: str = Form(...), password: str = Form(...)):
    return {'username': username}


"""Request Files 单文件、多文件上传及参数详解"""


@app04.post('/file')
def up_file(file: bytes = File(...)):
    """使用File类  文件内容以bytes的形式读入内存，适合于上传小文件"""
    return {'filesize': len(file)}


@app04.post('/file/list')
async def up_file_list(file: list[bytes] = File(...)):
    """使用File类  上传多个文件"""
    return {'filenum': len(file), 'filesize': len(file[0])}


@app04.post('/upload_file')
async def upload_file(file: UploadFile = File(...)):
    """
    使用UploadFile类
    1、文件存储在内存中，使用的内存达到阀值后，将被保存在磁盘中
    2、适合于图片、视频大文件
    3、可以获取上传文件的元数据，如文件名、创建时间等
    4、有文件对象的异步接口
    5、上传的文件是Python文件对象，可以使用write(),read(),seek(),close()等操作
    :param file:
    :return:
    """
    contents = await file.read()    # 异步调用
    print(contents)
    return {'filename': file.filename, 'content_type': file.content_type, 'size': file.size}


"""[见run.py] FastAPi项目的静态文件配置"""

""" Path Operation Configuration路径操作配置"""


@app04.post('/path_operation_configuration',
            response_model=UserOut,
            # tags=['Path', "Operation", "Configuration"],
            summary="This is summary",
            description="This is Description",
            response_description="This is Response Description",
            # deprecated=True,
            status_code=status.HTTP_200_OK)
async def path_operation_configuration(user: UserIn):
    """路径操作配置
    deprecated=True表示接口废弃
    """
    return user.model_dump()


"""[见run.py] FastAPi应用的常见配置项"""

"""Handling Errors 错误处理"""


@app04.get('/http_exception')
async def http_exception(city: str):
    if city != 'BJ':
        raise HTTPException(status_code=404, detail='Ciyt not found', headers={"X-code": "error"})
    return {"city": city}


@app04.get('/http_exception/{city_id}')
async def override_http_exception(city_id: int):
    if city_id != 110:
        raise HTTPException(status_code=418, detail='Ciyt_id not found', headers={"X-code": "error"})
    return {"city_id": city_id}
